﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Collections;
using DataAccessLogic;
using System.Data.SqlClient;
using System.Web.Security;
using System.Data;

namespace BusinessLogic
{
    [Serializable]
    public class Constituent : Table
    {
        #region Fields
        private string _firstName;
        private string _middleName;
        private string _lastName;
        private string _name;
        private string _lastNamePrefix = string.Empty;
        private bool _isOrganization = false;
        private bool _isPrimary = true;
        private bool _isActive = true;
        private bool _isSales = true;
        private bool _isService = true;
        private Address _address = null;
        private List<Address> _addresses = null;
        private Phone _phone = null;
        private List<Phone> _phones = null;
        private Email _emailAddress = null;
        private List<Email> _emailAddresses = null;
        private List<Relationship> _relationships = null;
        private List<Note> _notes = null;
        private Constituent _primaryContact = null;
        #endregion

        #region Methods
        public Constituent() { }
        
        /// <summary>
        /// This constructor fills every property on the constituent
        /// therefore if you call this from for instance a note class
        /// then you will have an infinite loop because we call GetAllByConstituentID
        /// on the notes class and everything else, etc.
        /// 
        /// Use the base constructor and then call FillByID().
        /// </summary>
        /// <param name="id"></param>
        public Constituent(Guid id)
        {                
            this._id = id;

            if(Guid.Empty != id)
            {
                this.FillByID();

                this.RefreshTables(Refresh.Address);
                this.RefreshTables(Refresh.Phone);
                this.RefreshTables(Refresh.Email);
                this.RefreshTables(Refresh.Relationship);
                this.RefreshTables(Refresh.Note);
            }
        }

        public void RefreshTables(Refresh refresh) 
        {
            if(Guid.Empty != this._id)
            {
                switch (refresh)
                {
                    case Refresh.Address:
                        this._addresses = Address.GetAllByConstituentID(this._id);
                    
                        if (this._addresses != null)
                        {
                            ReturnFirstOrDefault<Address>(this._addresses.Where(a => a.IsPrimary), ref this._address);
                        }
                        break;
                    case Refresh.Phone:
                        this._phones = Phone.GetAllByConstituentID(this._id);

                        if (this._phones != null)
                        {
                            ReturnFirstOrDefault<Phone>(this._phones.Where(p => p.IsPrimary), ref this._phone);
                        }
                        break;
                    case Refresh.Email:
                        this._emailAddresses = Email.GetAllByConstituentID(this._id);

                        if (this._emailAddresses != null)
                        {
                            ReturnFirstOrDefault<Email>(this._emailAddresses.Where(e => e.IsPrimary), ref this._emailAddress);
                        }
                        break;
                    case Refresh.Relationship:
                        this._relationships = Relationship.GetAllByConstituentID(this._id);
                        break;
                    case Refresh.Note:
                        this._notes = Note.GetAllByConstituentID(this._id);
                        break;
                    default:
                        break;
                }
            }
        }

        private void ReturnFirstOrDefault<T>(IEnumerable<T> tt, ref T t) 
        {
            if(tt != null && 0 < tt.Count())
            {
                t = tt.FirstOrDefault();
            }         
        }

        public bool Create()
        {
            try
            {
                this._id = ConstituentDataAccess.Create(this);
            
                if(_id != Guid.Empty)
                {
                    if((this._address != null) && (!string.IsNullOrWhiteSpace(this._address.AddressBlock)))
                    {
                        this._address.Create(this._id);
                    }

                    if ((this._phone != null) && (!string.IsNullOrWhiteSpace(this._phone.Number)))
                    {
                        this._phone.Create(this._id);
                    }

                    if ((this._emailAddress != null) && (!string.IsNullOrWhiteSpace(this._emailAddress.EmailAddress)))
                    {
                        this._emailAddress.Create(this._id);
                    }

                    return true;
                }    
                else
                {
                    return false;
                } 

            }
            catch 
            {                
                return false;   
            }      
        }

        public void CreateForConversion(bool isContact)
        {
            CreateForConversion(isContact, false);
        }

        public void CreateForConversion(bool isContact, bool isSpecialCase)
        {
            try
            {
                //create the basic stuff
                this._id = ConstituentDataAccess.CreateForConversion(this);

                if(_id != Guid.Empty)
                {
                    //create the addresses
                    if(_addresses != null && _addresses.Count > 0)
                    {
                        foreach(var add in _addresses)
                        {
                            add.CreateForConversion(_id);
                        }
                    }
                                        
                    //create the primary contact
                    if(_primaryContact != null)
                    {
                        _primaryContact.CreateForConversion(true);
                        
                        //create the phones
                        if (_primaryContact.Phones != null && _primaryContact.Phones.Count > 0)
                        {
                            foreach (var ph in _primaryContact.Phones)
                            {
                                ph.CreateForConversion(_primaryContact.ID);
                            }
                        }

                        //create the emails
                        if (_primaryContact.EmailAddresses != null && _primaryContact.EmailAddresses.Count > 0)
                        {
                            foreach (var em in _primaryContact.EmailAddresses)
                            {
                                em.CreateForConversion(_primaryContact.ID);
                            }
                        }
                    }
                    
                    //_relationships
                    if (isContact)
                    {
                        if(_relationships != null && _relationships.Count > 0)
                        {
                            foreach (var r in _relationships)
                            {
                                r.CreateForConversion();
                            }
                        }
                    }
                }
            }
            catch(Exception ex)
            { 
                throw ex;
            }
        }

        public static void ConversionPrep()
        {
            try
            {
                ConstituentDataAccess.ConversionPrep();
            }
            catch(Exception ex)
            {
                throw ex;
            }
        }

        private void CreateName()
        {
            if (string.IsNullOrWhiteSpace(_name))
            {
                if (_isOrganization)
                {
                    if (string.IsNullOrWhiteSpace(_lastNamePrefix))
                    {
                        _name = _lastName;
                    }
                    else
                    {
                        _name = string.Concat(_lastNamePrefix, " ", _lastName);
                    }
                }
                else
                {
                    if (string.IsNullOrWhiteSpace(_firstName))
                    {
                        _name = "";
                    }
                    else
                    {
                        _name = string.Concat(_firstName, " ");
                    }

                    if (string.IsNullOrWhiteSpace(_middleName))
                    {
                        _name = string.Concat(_name, "");
                    }
                    else
                    {
                        _name = string.Concat(_name, _middleName.Substring(0, 1), ".");
                    }

                    _name = string.Concat(_name, " ", _lastName);
                }
            }
        }

        public void Delete()
        {
            ConstituentDataAccess.Delete(this._id);
        }

        public void FillByID()
        {
            FillByID(this._id);
        }

        public void FillByID(Guid id)
        {
            if(Guid.Empty != id)
            {
                this._id = id;

                try
                {
                    Constituent c = ConstituentDataAccess.GetByID(id);
                    FirstName = c.FirstName;
                    MiddleName = c.MiddleName;
                    LastName = c.LastName;
                    LastNamePrefix = c.LastNamePrefix;
                    IsOrganization = c.IsOrganization;
                    IsActive = c.IsActive;
                    IsPrimary = c.IsPrimary;
                    IsService = c.IsService;
                    IsSales = c.IsSales;
                    c.CreateName();
                }
                catch { }                
            }
        }

        public static List<Constituent> CheckForDuplicate(Constituent constituent)
        {
            return CheckForDuplicate(constituent.Name);
        }

        public static List<Constituent> CheckForDuplicate(string name)
        {
            List<Constituent> dupes = null;

            if(!string.IsNullOrWhiteSpace(name))
            {
                dupes = ConstituentDataAccess.CheckForDuplicates(name);
            }

            return dupes;
        }        

        public static List<Constituent> GetActive()
        {
            return ConstituentDataAccess.GetActive();
        }

        public static List<String> GetActiveNames()
        {
            return ConstituentDataAccess.GetActiveNames();
        }

        public static DataTable GetActivePrimariesDataTable(string searchText)
        {
            DataTable dt = ConstituentDataAccess.GetActivePrimariesDataTable();
            
            if(!string.IsNullOrWhiteSpace(searchText))
            {   
                dt = GetActivePrimariesDataTable(searchText, dt);
            }            
            
            return dt;
        }

        public static DataTable GetActivePrimariesDataTable(string searchText, DataTable dt)
        {
            if(dt == null)
            {
                dt = GetActivePrimariesDataTable(searchText);
            }

            if(string.IsNullOrWhiteSpace(searchText))
            {
                return dt;
            }
            else
            {
                DataRow[] rows = dt.Select(string.Format("ORGANIZATION like '%{0}%' or PRIMARYCONTACT like '%{0}%'", searchText));
                if(rows.Length > 0)
                {
                    return rows.CopyToDataTable();
                }
                else
                {
                    return new DataTable();
                }
            }
        }

        public static List<Constituent> GetAll()
        {
            return ConstituentDataAccess.GetAll();
        }

        public static List<Constituent> Search(string name)
        {
            return ConstituentDataAccess.Search(name);
        }

        public static DataTable SearchAll()
        {
            return ConstituentDataAccess.SearchAll();
        }
        #endregion

        #region Properties
        public string FirstName
        {
            get
            {
                if(_firstName == null)
                {
                    _firstName = string.Empty;
                }

                return _firstName;
            }
            set
            {
                _firstName = value;
            }
        }

        public string MiddleName
        {
            get
            {
                return _middleName;
            }
            set
            {
                _middleName = value;
            }
        }

        public string LastName
        {
            get
            {
                return _lastName;
            }
            set
            {
                _lastName = value;
            }
        }

        public string LastNamePrefix
        {
            get
            {
                if (null == _lastNamePrefix)
                {
                    _lastNamePrefix = string.Empty;
                }

                return _lastNamePrefix;
            }
            set
            {
                _lastNamePrefix = value;
            }
        }

        public string Name
        {
            get
            {
                CreateName();
                return _name;
            }
            set
            {
                _name = value;
            }
        }

        public bool IsOrganization
        {
            get
            {
                return _isOrganization;
            }
            set
            {
                _isOrganization = value;
            }
        }

        public bool IsSales
        {
            get 
            {
                return _isSales;
            }
            set
            {
                _isSales = value;
            }
        }
        
        public bool IsService
        {
            get
            {
                return _isService;
            }
            set
            {
                _isService = value;
            }
        }

        public bool IsPrimary
        {
            get
            {
                return _isPrimary;
            }
            set
            {
                _isPrimary = value;
            }
        }

        public bool IsActive
        {
            get
            {
                return _isActive;
            }
            set
            {
                _isActive = value;
            }
        }

        public Address Address
        {
            get
            {
                try
                {
                    if (null == _address)
                    {
                        if (0 < _addresses.Count)
                        {
                            _address = _addresses[0];
                        }
                    }
                }
                catch (NullReferenceException)
                {
                    _address = null;
                }

                return _address;
            }
            set
            {
                _address = value;

                if (null == _addresses)
                {
                    _addresses = new List<Address>();
                }

                _addresses.Add(value);
            }
        }

        public List<Address> Addresses
        {
            get
            {
                return _addresses;
            }
            set
            {
                _addresses = value;
            }
        }

        public Email EmailAddress
        {
            get
            {
                try
                {
                    if (null == _emailAddress)
                    {
                        if (0 < _emailAddresses.Count)
                        {
                            _emailAddress = _emailAddresses[0];
                        }
                    }
                }
                catch (NullReferenceException)
                {
                    _emailAddress = null;
                }

                return _emailAddress;
            }
            set
            {
                _emailAddress = value;

                if (null == _emailAddresses)
                {
                    _emailAddresses = new List<Email>();
                }

                _emailAddresses.Add(value);
            }
        }

        public List<Email> EmailAddresses
        {
            get
            {
                return _emailAddresses;
            }
            set
            {
                _emailAddresses = value;
            }
        }

        public Phone Phone
        {
            get
            {
                try
                {
                    if (null == _phone)
                    {
                        if (0 < _phones.Count)
                        {
                            _phone = _phones[0];
                        }
                    }
                }
                catch (NullReferenceException)
                {
                    _phone = null;
                }

                return _phone;
            }
            set
            {
                _phone = value;

                if (null == _phones)
                {
                    _phones = new List<Phone>();
                }

                _phones.Add(value);
            }
        }

        public List<Phone> Phones
        {
            get
            {
                return _phones;
            }
            set
            {
                _phones = value;
            }
        }

        public List<Relationship> Relationships
        {
            get
            {
                return _relationships;
            }
            set
            {
                _relationships = value;
            }
        }

        public List<Note> Notes
        {
            get 
            {
                return _notes;
            }
            set
            {
                _notes = value;
            }
        }

        public Constituent PrimaryContact
        {
            get
            {
                return _primaryContact;
            }
            set
            {
                _primaryContact = value;
            }
        }
        #endregion

        public enum Refresh
        {
            Address,
            Phone,
            Email,
            Relationship,
            Note
        }
    }
}